/* 
 * File:   V4LCapture.cpp
 * Author: gustavo
 * 
 * Created on August 29, 2012, 11:08 AM
 */

#include "sys/stat.h"
#include "stdio.h"

#include <list>

#include "v4l_capture.hpp"

namespace imp {
	namespace capture {

		/* = Constructors =================================================== */
		V4LCapture::V4LCapture() {
			v4l_drv.fd = -1;
		}

		V4LCapture::~V4LCapture() {
		}

		/* = Methods ======================================================== */
		bool V4LCapture::open(const char * device) {

			v4l_drv = v4l_open_default(device);

			if (v4l_drv.fd < 0) return false;

			return true;
		}

		bool V4LCapture::is_opened() {
			return (v4l_drv.fd != -1);
		}

		bool V4LCapture::close() {
			v4l_close(&v4l_drv);
			return true;
		}

		bool V4LCapture::start() {
			v4l_start(&v4l_drv);
		}

		bool V4LCapture::stop() {
			v4l_stop(&v4l_drv);
		}

		void * V4LCapture::grab_raw() {
			v4l_grab_raw(&v4l_drv);
		}

		void V4LCapture::get_image_size(int* width, int* height) {
			*width = v4l_drv.width;
			*height = v4l_drv.height;
		}

		void V4LCapture::grab_and_fill_gray(char * gray) {
			v4l_grab_gray(&v4l_drv, gray);
		}

		void V4LCapture::grab_and_fill_rgb(char * rgb) {
			v4l_grab_rgb(&v4l_drv, rgb);
		}

		/* = Useful methods ================================================= */
		std::list< char* > * V4LCapture::get_device_list() {

			std::list<char*> * dlist = new std::list<char*>();

			struct stat st;
			char * name;
			int n = 0;

			while (n < 20) {
				name = (char *) calloc(DEVICE_NAME_MAX_LENGTH, sizeof (char));
				snprintf(name, DEVICE_NAME_MAX_LENGTH, "/dev/video%d", n);

				if (stat(name, &st) != 0) {
					free(name);
				} else {
					dlist->push_back(name);
				}
				n++;
			}
			return dlist;
		}

		const char * V4LCapture::get_device_card() {
			return (const char *) v4l_drv.vcap.card;
		}

		const char * V4LCapture::get_device_driver() {
			return (const char *) v4l_drv.vcap.driver;
		}

		const char * V4LCapture::get_device_bus() {
			return (const char *) v4l_drv.vcap.bus_info;
		}

		/* = Enumerations =================================================== */
		bool V4LCapture::enum_input(struct v4l2_input * input, int init) {
			return v4l_enum_input(&v4l_drv, input, init, 0);
		}

		bool V4LCapture::enum_standard(struct v4l2_standard * standard, int init) {
			return v4l_enum_standard(&v4l_drv, standard, init, 0);
		}

		bool V4LCapture::enum_format_desc(struct v4l2_fmtdesc * fmtdesc, int init) {
			return v4l_enum_format_desc(&v4l_drv, fmtdesc, init, 0);
		}

		bool V4LCapture::enum_frame_size(struct v4l2_frmsizeenum * frmsize, int init) {

			struct v4l2_format format;

			if (!get_format(&format)) return false;

			return v4l_enum_frame_size(&v4l_drv, frmsize, format.fmt.pix.pixelformat, init, 0);
		}

		bool V4LCapture::enum_control_default(struct v4l2_queryctrl* qctrl, int init) {
			return v4l_enum_control(&v4l_drv, qctrl, init);
		}

		bool V4LCapture::enum_control_user(struct v4l2_queryctrl* qctrl, int init) {
			return v4l_enum_control_user(&v4l_drv, qctrl, init);
		}

		bool V4LCapture::enum_control_private(struct v4l2_queryctrl* qctrl, int init) {
			return v4l_enum_control_private(&v4l_drv, qctrl, init);
		}

		/* ================================================================== */
		bool V4LCapture::get_input(struct v4l2_input * input) {

			return v4l_get_input(&v4l_drv, input);
		}

		bool V4LCapture::get_standard(struct v4l2_standard * standard) {

			return v4l_get_standard(&v4l_drv, standard);
		}

		bool V4LCapture::get_format(struct v4l2_format * format) {

			return v4l_get_format(&v4l_drv, format);
		}

		bool V4LCapture::get_format_desc(struct v4l2_fmtdesc * fmtdesc) {

			return v4l_get_format_description(&v4l_drv, fmtdesc);
		}

		bool V4LCapture::get_control(struct v4l2_control * ctrl, int ctrl_id) {
			return v4l_get_control(&v4l_drv, ctrl, ctrl_id);
		}
		
		bool V4LCapture::get_control_menu(struct v4l2_querymenu * qmenu, int ctrl_id, int index) {
			return v4l_enum_control_menu(&v4l_drv, qmenu, ctrl_id, index);
		}

		/* ================================================================== */
		bool V4LCapture::set_input(int index) {
			v4l_set_input(&v4l_drv, index);
		}

		bool V4LCapture::set_standard(int id) {
			v4l_set_standard(&v4l_drv, (v4l2_std_id) id);
		}

		bool V4LCapture::set_pixel_format(int pixel_format) {
			v4l_set_pixel_format(&v4l_drv, pixel_format);
		}

		bool V4LCapture::set_frame_size(int width, int height) {
			v4l_set_frame_size(&v4l_drv, width, height);
		}
		
		bool V4LCapture::set_control(int ctrl_id, int value) {
			v4l_set_control(&v4l_drv, ctrl_id, value);
		}

	}
}